# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
import os

from yacs.config import CfgNode as CN

# -----------------------------------------------------------------------------
# Convention about Training / Test specific parameters
# -----------------------------------------------------------------------------
# Whenever an argument can be either used for training or for testing, the
# corresponding name will be post-fixed by a _TRAIN for a training parameter,
# or _TEST for a test-specific parameter.
# For example, the number of images during training will be
# IMAGES_PER_BATCH_TRAIN, while the number of images for testing will be
# IMAGES_PER_BATCH_TEST

# -----------------------------------------------------------------------------
# Config definition
# -----------------------------------------------------------------------------

_C = CN()
# Precision of input, allowable: (float32, float16)
_C.DTYPE = "float32"
_C.AMP_VERBOSE = False

_C.MODEL = CN()
_C.MODEL.RPN_ONLY = False
_C.MODEL.MASK_ON = False
_C.MODEL.SHAPE_ON = False
_C.MODEL.RETINANET_ON = False
_C.MODEL.STEREO_ON = False
_C.MODEL.DET3D_ON = False
_C.MODEL.DEVICE = "cuda"
_C.MODEL.META_ARCHITECTURE = "GeneralizedRCNN"
_C.MODEL.CLS_AGNOSTIC_BBOX_REG = False

# If the WEIGHT starts with a catalog://, like :R-50, the code will look for
# the path in paths_catalog. Else, it will use it as the specified absolute
# path
_C.MODEL.WEIGHT = ""

# -----------------------------------------------------------------------------
# INPUT
# -----------------------------------------------------------------------------
_C.INPUT = CN()
# Size of the smallest side of the image during training
_C.INPUT.DO_RESIZE = True
_C.INPUT.MIN_SIZE_TRAIN = (8000,)  # (800,)
# Maximum size of the side of the image during training
_C.INPUT.MAX_SIZE_TRAIN = 1333
# Size of the smallest side of the image during testing
_C.INPUT.MIN_SIZE_TEST = 800
# Maximum size of the side of the image during testing
_C.INPUT.MAX_SIZE_TEST = 1333
# Values to be used for image normalization
_C.INPUT.PIXEL_MEAN = [102.9801, 115.9465, 122.7717]
# Values to be used for image normalization
_C.INPUT.PIXEL_STD = [1., 1., 1.]
# Image resize Interpolation method
# Convert image to BGR format (for Caffe2 models), in range 0-255
_C.INPUT.TO_BGR255 = True
_C.INPUT.FLIP_PROB_TRAIN = 0.5
_C.INPUT.SHUFFLE = True
_C.INPUT.BRIGHTNESS = 0.0
_C.INPUT.CONTRAST = 0.0
_C.INPUT.SATURATION = 0.0
_C.INPUT.HUE = 0.0
# -----------------------------------------------------------------------------
# Dataset
# -----------------------------------------------------------------------------
_C.DATASETS = CN()
# List of the dataset names for training, as present in paths_catalog.py
_C.DATASETS.TRAIN = ()
# List of the dataset names for testing, as present in paths_catalog.py
_C.DATASETS.TEST = ()

# -----------------------------------------------------------------------------
# DataLoader
# -----------------------------------------------------------------------------
_C.DATALOADER = CN()
# Number of data loading threads
_C.DATALOADER.NUM_WORKERS = 4
# If > 0, this enforces that each collated batch should have a size divisible
# by SIZE_DIVISIBILITY
_C.DATALOADER.SIZE_DIVISIBILITY = 0
# If True, each batch should contain only images for which the aspect ratio
# is compatible. This groups portrait images together, and landscape images
# are not batched with portrait images.
_C.DATALOADER.ASPECT_RATIO_GROUPING = True

# ---------------------------------------------------------------------------- #
# Backbone options
# ---------------------------------------------------------------------------- #
_C.MODEL.BACKBONE = CN()

# The backbone conv body to use
# The string must match a function that is imported in modeling.model_builder
# (e.g., 'FPN.add_fpn_ResNet101_conv5_body' to specify a ResNet-101-FPN
# backbone)
_C.MODEL.BACKBONE.CONV_BODY = "R-50-C4"

# Add StopGrad at a specified stage so the bottom layers are frozen
_C.MODEL.BACKBONE.FREEZE_CONV_BODY_AT = 2
# GN for backbone
_C.MODEL.BACKBONE.USE_GN = False

# ---------------------------------------------------------------------------- #
# FPN options
# ---------------------------------------------------------------------------- #
_C.MODEL.FPN = CN()
_C.MODEL.FPN.USE_GN = False
_C.MODEL.FPN.USE_RELU = False

# ---------------------------------------------------------------------------- #
# Group Norm options
# ---------------------------------------------------------------------------- #
_C.MODEL.GROUP_NORM = CN()
# Number of dimensions per group in GroupNorm (-1 if using NUM_GROUPS)
_C.MODEL.GROUP_NORM.DIM_PER_GP = -1
# Number of groups in GroupNorm (-1 if using DIM_PER_GP)
_C.MODEL.GROUP_NORM.NUM_GROUPS = 32
# GroupNorm's small constant in the denominator
_C.MODEL.GROUP_NORM.EPSILON = 1e-5

# ---------------------------------------------------------------------------- #
# RPN options
# ---------------------------------------------------------------------------- #
_C.MODEL.RPN = CN()
_C.MODEL.RPN.USE_FPN = False
# Base RPN anchor sizes given in absolute pixels w.r.t. the scaled network input
_C.MODEL.RPN.ANCHOR_SIZES = (32, 64, 128, 256, 512)
# Stride of the feature map that RPN is attached.
# For FPN, number of strides should match number of scales
_C.MODEL.RPN.ANCHOR_STRIDE = (16,)
# RPN anchor aspect ratios
_C.MODEL.RPN.ASPECT_RATIOS = (0.5, 1.0, 2.0)
# Remove RPN anchors that go outside the image by RPN_STRADDLE_THRESH pixels
# Set to -1 or a large value, e.g. 100000, to disable pruning anchors
_C.MODEL.RPN.STRADDLE_THRESH = 0
# Minimum overlap required between an anchor and ground-truth box for the
# (anchor, gt box) pair to be a positive example (IoU >= FG_IOU_THRESHOLD
# ==> positive RPN example)
_C.MODEL.RPN.FG_IOU_THRESHOLD = 0.7
# Maximum overlap allowed between an anchor and ground-truth box for the
# (anchor, gt box) pair to be a negative examples (IoU < BG_IOU_THRESHOLD
# ==> negative RPN example)
_C.MODEL.RPN.BG_IOU_THRESHOLD = 0.3
# Total number of RPN examples per image
_C.MODEL.RPN.BATCH_SIZE_PER_IMAGE = 256
# Target fraction of foreground (positive) examples per RPN minibatch
_C.MODEL.RPN.POSITIVE_FRACTION = 0.5
# Number of top scoring RPN proposals to keep before applying NMS
# When FPN is used, this is *per FPN level* (not total)
_C.MODEL.RPN.PRE_NMS_TOP_N_TRAIN = 12000
_C.MODEL.RPN.PRE_NMS_TOP_N_TEST = 6000
# Number of top scoring RPN proposals to keep after applying NMS
_C.MODEL.RPN.POST_NMS_TOP_N_TRAIN = 2000
_C.MODEL.RPN.POST_NMS_TOP_N_TEST = 1000
# NMS threshold used on RPN proposals
_C.MODEL.RPN.NMS_THRESH = 0.7
# Proposal height and width both need to be greater than RPN_MIN_SIZE
# (a the scale used during training or inference)
_C.MODEL.RPN.MIN_SIZE = 0
# Number of top scoring RPN proposals to keep after combining proposals from
# all FPN levels
_C.MODEL.RPN.FPN_POST_NMS_TOP_N_TRAIN = 2000
_C.MODEL.RPN.FPN_POST_NMS_TOP_N_TEST = 2000
# Custom rpn head, empty to use default conv or separable conv
_C.MODEL.RPN.RPN_HEAD = "SingleConvRPNHead"

# -----------------------------------------------------------------------
# PointRCNN options
# -----------------------------------------------------------------------
# for PointRCNN
# config of network structure
_C.MODEL.PCNET = CN()
_C.MODEL.PCNET.MAX_ROI_FOR_TRAINING = 20

_C.MODEL.POINTRCNN = CN()
_C.MODEL.POINTRCNN.TRAINED_MODEL = ''
_C.MODEL.POINTRCNN.RESIZE_BACK = True
_C.MODEL.POINTRCNN.MAX_ROI_FOR_TRAINING = 20
_C.MODEL.POINTRCNN.AUG_DATA = True
_C.MODEL.POINTRCNN.RPN = CN()
_C.MODEL.POINTRCNN.RPN.NPOINTS = 768
_C.MODEL.POINTRCNN.RPN.EARLY_INTEGRATE = False
_C.MODEL.POINTRCNN.RPN.INTERVAL = 5
_C.MODEL.POINTRCNN.RPN.VOXEL_SIZE = (0.1, 0.1)
_C.MODEL.POINTRCNN.RPN.DETECT_THRESH = 1
_C.MODEL.POINTRCNN.RPN.NUM_POINT_THRESH = 10
_C.MODEL.POINTRCNN.RPN.IOU_THRESH = 0.2
_C.MODEL.POINTRCNN.RPN.USE_BACKEND_COV = True

_C.MODEL.POINTRCNN.RPN.ENABLED = True
_C.MODEL.POINTRCNN.RPN.FIXED = False

_C.MODEL.POINTRCNN.RPN.USE_ROAD = True
_C.MODEL.POINTRCNN.RPN.USE_INTENSITY = True
_C.MODEL.POINTRCNN.RPN.USE_BN = True

_C.MODEL.POINTRCNN.RPN.SA_CONFIG = CN()
_C.MODEL.POINTRCNN.RPN.SA_CONFIG.NPOINTS = [4096, 1024, 256, 64]
_C.MODEL.POINTRCNN.RPN.SA_CONFIG.RADIUS = [[0.1, 0.5], [0.5, 1.0], [1.0, 2.0], [2.0, 4.0]]
_C.MODEL.POINTRCNN.RPN.SA_CONFIG.NSAMPLE = [[16, 32], [16, 32], [16, 32], [16, 32]]
_C.MODEL.POINTRCNN.RPN.SA_CONFIG.MLPS = [[[16, 16, 32], [32, 32, 64]],
                                         [[64, 64, 128], [64, 96, 128]],
                                         [[128, 196, 256], [128, 196, 256]],
                                         [[256, 256, 512], [256, 384, 512]]]
_C.MODEL.POINTRCNN.RPN.FP_MLPS = [[128, 128], [256, 256], [512, 512], [512, 512]]
_C.MODEL.POINTRCNN.RPN.CLS_FC = [128]
_C.MODEL.POINTRCNN.RPN.REG_FC = [128]
_C.MODEL.POINTRCNN.RPN.DP_RATIO = 0.5
# config of bin-based loss
_C.MODEL.POINTRCNN.RPN.LOC_XZ_FINE = False
_C.MODEL.POINTRCNN.RPN.LOC_SCOPE = 3.0
_C.MODEL.POINTRCNN.RPN.LOC_BIN_SIZE = 0.5
_C.MODEL.POINTRCNN.RPN.NUM_HEAD_BIN = 12  # pointrcnn's
# config of training
_C.MODEL.POINTRCNN.RPN.LOSS_CLS = 'SigmoidFocalLoss'
_C.MODEL.POINTRCNN.RPN.FG_WEIGHT = 15
_C.MODEL.POINTRCNN.RPN.FOCAL_ALPHA = [0.25, 0.75]
_C.MODEL.POINTRCNN.RPN.FOCAL_GAMMA = 2.0
_C.MODEL.POINTRCNN.RPN.REG_LOSS_WEIGHT = [1.0, 1.0, 1.0, 1.0]
_C.MODEL.POINTRCNN.RPN.LOSS_WEIGHT = [1.0, 1.0]
_C.MODEL.POINTRCNN.RPN.NMS_TYPE = 'normal'  # normal, rotate

# config of testing
_C.MODEL.POINTRCNN.RPN.SCORE_THRESH = 0.3
# config of rgb image
_C.MODEL.POINTRCNN.RPN.USE_RGB = False
_C.MODEL.POINTRCNN.RPN.FIX_RGB_NET = False
_C.MODEL.POINTRCNN.RPN.IMG_FEATURE_STRIDE = 2

# For voxel head
_C.MODEL.POINTRCNN.FUSION3D = False
_C.MODEL.POINTRCNN.PREDICT_OFFSET = False
_C.MODEL.POINTRCNN.KMEANS = False
_C.MODEL.POINTRCNN.VOXEL_FUSION = "VoxelFusionMLP2d"
_C.MODEL.POINTRCNN.VOTING_MASK = False
_C.MODEL.POINTRCNN.NMS_BEFORE = False
_C.MODEL.POINTRCNN.MASK_MIN_AREA_PER_IM = 250
_C.MODEL.POINTRCNN.MIN_NUM_POINT_IN_ROI = 3
_C.MODEL.POINTRCNN.LOSS_WEIGHT = 0.1
_C.MODEL.POINTRCNN.MASK_THRESH = 0.7
_C.MODEL.POINTRCNN.AUG_ROT_RANGE = 18

# 2. config of rcnn network

_C.MODEL.POINTRCNN.RCNN = CN()
_C.MODEL.POINTRCNN.RCNN.ENABLED = False
_C.MODEL.POINTRCNN.RCNN.TRAIN = True

# config of input
_C.MODEL.POINTRCNN.RCNN.USE_RPN_FEATURES = True
_C.MODEL.POINTRCNN.RCNN.USE_MASK = True
_C.MODEL.POINTRCNN.RCNN.MASK_TYPE = 'seg'
_C.MODEL.POINTRCNN.RCNN.USE_INTENSITY = False
_C.MODEL.POINTRCNN.RCNN.USE_DEPTH = True
_C.MODEL.POINTRCNN.RCNN.USE_SEG_SCORE = False
_C.MODEL.POINTRCNN.RCNN.ROI_FROM_ALL_SCENE = True
_C.MODEL.POINTRCNN.RCNN.ROI_SAMPLE_JIT = True
_C.MODEL.POINTRCNN.RCNN.ROI_FG_AUG_TIMES = 10

_C.MODEL.POINTRCNN.RCNN.REG_AUG_METHOD = 'multiple'  # multiple, single, normal
_C.MODEL.POINTRCNN.RCNN.TRAINING_BOX_FILE = ''
_C.MODEL.POINTRCNN.RCNN.POOL_EXTRA_WIDTH = 1.0

# config of bin-based loss
_C.MODEL.POINTRCNN.RCNN.LOC_SCOPE = 1.5
_C.MODEL.POINTRCNN.RCNN.LOC_BIN_SIZE = 0.5
_C.MODEL.POINTRCNN.RCNN.NUM_HEAD_BIN = 9
_C.MODEL.POINTRCNN.RCNN.LOC_Y_BY_BIN = False
_C.MODEL.POINTRCNN.RCNN.LOC_Y_SCOPE = 0.5
_C.MODEL.POINTRCNN.RCNN.LOC_Y_BIN_SIZE = 0.25
_C.MODEL.POINTRCNN.RCNN.SIZE_RES_ON_ROI = False

# config of network structure
_C.MODEL.POINTRCNN.RCNN.USE_BN = False
_C.MODEL.POINTRCNN.RCNN.DP_RATIO = 0.0

_C.MODEL.POINTRCNN.RCNN.BACKBONE = 'pointnet'  # pointnet, pointsift
_C.MODEL.POINTRCNN.RCNN.XYZ_UP_LAYER = [128, 128]

_C.MODEL.POINTRCNN.RCNN.NUM_POINTS = 512
_C.MODEL.POINTRCNN.RCNN.SA_CONFIG = CN()
_C.MODEL.POINTRCNN.RCNN.SA_CONFIG.NPOINTS = [128, 32, -1]
_C.MODEL.POINTRCNN.RCNN.SA_CONFIG.RADIUS = [0.2, 0.4, 100]
_C.MODEL.POINTRCNN.RCNN.SA_CONFIG.NSAMPLE = [64, 64, 64]
_C.MODEL.POINTRCNN.RCNN.SA_CONFIG.MLPS = [[128, 128, 128],
                                          [128, 128, 256],
                                          [256, 256, 512]]
_C.MODEL.POINTRCNN.RCNN.CLS_FC = [256, 256]
_C.MODEL.POINTRCNN.RCNN.REG_FC = [256, 256]

# config of training
_C.MODEL.POINTRCNN.RCNN.LOSS_CLS = 'BinaryCrossEntropy'
_C.MODEL.POINTRCNN.RCNN.FOCAL_ALPHA = [0.25, 0.75]
_C.MODEL.POINTRCNN.RCNN.FOCAL_GAMMA = 2.0
_C.MODEL.POINTRCNN.RCNN.CLS_WEIGHT = [1.0, 1.0, 1.0]
_C.MODEL.POINTRCNN.RCNN.CLS_FG_THRESH = 0.6
_C.MODEL.POINTRCNN.RCNN.CLS_BG_THRESH = 0.45
_C.MODEL.POINTRCNN.RCNN.CLS_BG_THRESH_LO = 0.05
_C.MODEL.POINTRCNN.RCNN.REG_FG_THRESH = 0.55
_C.MODEL.POINTRCNN.RCNN.FG_RATIO = 0.5
_C.MODEL.POINTRCNN.RCNN.ROI_PER_IMAGE = 64
_C.MODEL.POINTRCNN.RCNN.HARD_BG_RATIO = 0.8

# config of testing
_C.MODEL.POINTRCNN.RCNN.SCORE_THRESH = 0.1
_C.MODEL.POINTRCNN.RCNN.NMS_THRESH = 0.1

# some other config
# _C.MODEL.POINTRCNN.CLS_MEAN_SIZE = [[[0.84481201, 0.55790696, 0.62615112]]]
_C.MODEL.POINTRCNN.TRAIN = CN()
_C.MODEL.POINTRCNN.TEST = CN()
_C.MODEL.POINTRCNN.MEAN_SIZE = [[3.88311640418, 1.62856739989, 1.52563191462]]

_C.MODEL.POINTRCNN.TRAIN.RPN_PRE_NMS_TOP_N = 512
_C.MODEL.POINTRCNN.TRAIN.RPN_POST_NMS_TOP_N = 128
_C.MODEL.POINTRCNN.TRAIN.RPN_NMS_THRESH = 0.85
_C.MODEL.POINTRCNN.TRAIN.RPN_DISTANCE_BASED_PROPOSE = False
_C.MODEL.POINTRCNN.TRAIN.GRAD_NORM_CLIP = 1.0

_C.MODEL.POINTRCNN.TEST.RPN_PRE_NMS_TOP_N = 512
_C.MODEL.POINTRCNN.TEST.RPN_POST_NMS_TOP_N = 64
_C.MODEL.POINTRCNN.TEST.RPN_NMS_THRESH = 0.8
_C.MODEL.POINTRCNN.TEST.RPN_DISTANCE_BASED_PROPOSE = False

# ---------------------------------------------------------------------------- #
# ROI HEADS options
# ---------------------------------------------------------------------------- #
_C.MODEL.ROI_HEADS = CN()
_C.MODEL.ROI_HEADS.USE_FPN = False
# Overlap threshold for an RoI to be considered foreground (if >= FG_IOU_THRESHOLD)
_C.MODEL.ROI_HEADS.FG_IOU_THRESHOLD = 0.5
# Overlap threshold for an RoI to be considered background
# (class = 0 if overlap in [0, BG_IOU_THRESHOLD))
_C.MODEL.ROI_HEADS.BG_IOU_THRESHOLD = 0.5
# Default weights on (dx, dy, dw, dh) for normalizing bbox regression targets
# These are empirically chosen to approximately lead to unit variance targets
_C.MODEL.ROI_HEADS.BBOX_REG_WEIGHTS = (10., 10., 5., 5.)
# RoI minibatch size *per image* (number of regions of interest [ROIs])
# Total number of RoIs per training minibatch =
#   TRAIN.BATCH_SIZE_PER_IM * TRAIN.IMS_PER_BATCH
# E.g., a common configuration is: 512 * 2 * 8 = 8192
_C.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 512
# Target fraction of RoI minibatch that is labeled foreground (i.e. class > 0)
_C.MODEL.ROI_HEADS.POSITIVE_FRACTION = 0.25

# Only used on test mode

# Minimum score threshold (assuming scores in a [0, 1] range); a value chosen to
# balance obtaining high recall with not having too many low precision
# detections that will slow down inference post processing steps (like NMS)
_C.MODEL.ROI_HEADS.SCORE_THRESH = 0.05
# Overlap threshold used for non-maximum suppression (suppress boxes with
# IoU >= this threshold)
_C.MODEL.ROI_HEADS.NMS = 0.5
# Maximum number of detections to return per image (100 is based on the limit
# established for the COCO dataset)
_C.MODEL.ROI_HEADS.DETECTIONS_PER_IMG = 100

_C.MODEL.ROI_BOX_HEAD = CN()
_C.MODEL.ROI_BOX_HEAD.FEATURE_EXTRACTOR = "ResNet50Conv5ROIFeatureExtractor"
_C.MODEL.ROI_BOX_HEAD.PREDICTOR = "FastRCNNPredictor"
_C.MODEL.ROI_BOX_HEAD.POOLER_RESOLUTION = 14
_C.MODEL.ROI_BOX_HEAD.POOLER_SAMPLING_RATIO = 0
_C.MODEL.ROI_BOX_HEAD.POOLER_SCALES = (1.0 / 16,)
_C.MODEL.ROI_BOX_HEAD.NUM_CLASSES = 81
# Hidden layer dimension when using an MLP for the RoI box head
_C.MODEL.ROI_BOX_HEAD.MLP_HEAD_DIM = 1024
# GN
_C.MODEL.ROI_BOX_HEAD.USE_GN = False
# Dilation
_C.MODEL.ROI_BOX_HEAD.DILATION = 1
_C.MODEL.ROI_BOX_HEAD.CONV_HEAD_DIM = 256
_C.MODEL.ROI_BOX_HEAD.NUM_STACKED_CONVS = 4

_C.MODEL.ROI_MASK_HEAD = CN()
_C.MODEL.ROI_MASK_HEAD.FEATURE_EXTRACTOR = "ResNet50Conv5ROIFeatureExtractor"
_C.MODEL.ROI_MASK_HEAD.PREDICTOR = "MaskRCNNC4Predictor"
_C.MODEL.ROI_MASK_HEAD.POOLER_RESOLUTION = 14
_C.MODEL.ROI_MASK_HEAD.POOLER_SAMPLING_RATIO = 0
_C.MODEL.ROI_MASK_HEAD.POOLER_SCALES = (1.0 / 16,)
_C.MODEL.ROI_MASK_HEAD.MLP_HEAD_DIM = 1024
_C.MODEL.ROI_MASK_HEAD.CONV_LAYERS = (256, 256, 256, 256)
_C.MODEL.ROI_MASK_HEAD.RESOLUTION = 14
_C.MODEL.ROI_MASK_HEAD.SHARE_BOX_FEATURE_EXTRACTOR = True
# Whether or not resize and translate masks to the input image.
_C.MODEL.ROI_MASK_HEAD.POSTPROCESS_MASKS = False
_C.MODEL.ROI_MASK_HEAD.POSTPROCESS_MASKS_THRESHOLD = 0.5
# Dilation
_C.MODEL.ROI_MASK_HEAD.DILATION = 1
# GN
_C.MODEL.ROI_MASK_HEAD.USE_GN = False

_C.MODEL.ROI_SHAPE_HEAD = CN()
_C.MODEL.ROI_SHAPE_HEAD.POOLER_RESOLUTION = 14
_C.MODEL.ROI_SHAPE_HEAD.POOLER_SAMPLING_RATIO = 0
_C.MODEL.ROI_SHAPE_HEAD.POOLER_SCALES = (1.0 / 16,)
_C.MODEL.ROI_SHAPE_HEAD.MLP_HEAD_DIM = 1024
_C.MODEL.ROI_SHAPE_HEAD.HIDDEN_DIM = 5
_C.MODEL.ROI_SHAPE_HEAD.USE_GN = False
_C.MODEL.ROI_SHAPE_HEAD.SHARE_BOX_FEATURE_EXTRACTOR = True

# ---------------------------------------------------------------------------- #
# ResNe[X]t options (ResNets = {ResNet, ResNeXt}
# Note that parts of a resnet may be used for both the backbone and the head
# These options apply to both
# ---------------------------------------------------------------------------- #
_C.MODEL.RESNETS = CN()

# Number of groups to use; 1 ==> ResNet; > 1 ==> ResNeXt
_C.MODEL.RESNETS.NUM_GROUPS = 1

# Baseline width of each group
_C.MODEL.RESNETS.WIDTH_PER_GROUP = 64

# Place the stride 2 conv on the 1x1 filter
# Use True only for the original MSRA ResNet; use False for C2 and Torch models
_C.MODEL.RESNETS.STRIDE_IN_1X1 = True

# Residual transformation function
_C.MODEL.RESNETS.TRANS_FUNC = "BottleneckWithFixedBatchNorm"
# ResNet's stem function (conv1 and pool1)
_C.MODEL.RESNETS.STEM_FUNC = "StemWithFixedBatchNorm"

# Apply dilation in stage "res5"
_C.MODEL.RESNETS.RES5_DILATION = 1

_C.MODEL.RESNETS.BACKBONE_OUT_CHANNELS = 256 * 4
_C.MODEL.RESNETS.RES2_OUT_CHANNELS = 256
_C.MODEL.RESNETS.STEM_OUT_CHANNELS = 64

# ---------------------------------------------------------------------------- #
# RetinaNet Options (Follow the Detectron version)
# ---------------------------------------------------------------------------- #
_C.MODEL.RETINANET = CN()

# This is the number of foreground classes and background.
_C.MODEL.RETINANET.NUM_CLASSES = 81

# Anchor aspect ratios to use
_C.MODEL.RETINANET.ANCHOR_SIZES = (32, 64, 128, 256, 512)
_C.MODEL.RETINANET.ASPECT_RATIOS = (0.5, 1.0, 2.0)
_C.MODEL.RETINANET.ANCHOR_STRIDES = (8, 16, 32, 64, 128)
_C.MODEL.RETINANET.STRADDLE_THRESH = 0

# Anchor scales per octave
_C.MODEL.RETINANET.OCTAVE = 2.0
_C.MODEL.RETINANET.SCALES_PER_OCTAVE = 3

# Use C5 or P5 to generate P6
_C.MODEL.RETINANET.USE_C5 = True

# Convolutions to use in the cls and bbox tower
# NOTE: this doesn't include the last conv for logits
_C.MODEL.RETINANET.NUM_CONVS = 4

# Weight for bbox_regression loss
_C.MODEL.RETINANET.BBOX_REG_WEIGHT = 4.0

# Smooth L1 loss beta for bbox regression
_C.MODEL.RETINANET.BBOX_REG_BETA = 0.11

# During inference, #locs to select based on cls score before NMS is performed
# per FPN level
_C.MODEL.RETINANET.PRE_NMS_TOP_N = 1000

# IoU overlap ratio for labeling an anchor as positive
# Anchors with >= iou overlap are labeled positive
_C.MODEL.RETINANET.FG_IOU_THRESHOLD = 0.5

# IoU overlap ratio for labeling an anchor as negative
# Anchors with < iou overlap are labeled negative
_C.MODEL.RETINANET.BG_IOU_THRESHOLD = 0.4

# Focal loss parameter: alpha
_C.MODEL.RETINANET.LOSS_ALPHA = 0.25

# Focal loss parameter: gamma
_C.MODEL.RETINANET.LOSS_GAMMA = 2.0

# Prior prob for the positives at the beginning of training. This is used to set
# the bias init for the logits layer
_C.MODEL.RETINANET.PRIOR_PROB = 0.01

# Inference cls score threshold, anchors with score > INFERENCE_TH are
# considered for inference
_C.MODEL.RETINANET.INFERENCE_TH = 0.05

# NMS threshold used in RetinaNet
_C.MODEL.RETINANET.NMS_TH = 0.4

# ---------------------------------------------------------------------------- #
# FBNet options
# ---------------------------------------------------------------------------- #
_C.MODEL.FBNET = CN()
_C.MODEL.FBNET.ARCH = "default"
# custom arch
_C.MODEL.FBNET.ARCH_DEF = ""
_C.MODEL.FBNET.BN_TYPE = "bn"
_C.MODEL.FBNET.SCALE_FACTOR = 1.0
# the output channels will be divisible by WIDTH_DIVISOR
_C.MODEL.FBNET.WIDTH_DIVISOR = 1
_C.MODEL.FBNET.DW_CONV_SKIP_BN = True
_C.MODEL.FBNET.DW_CONV_SKIP_RELU = True

# > 0 scale, == 0 skip, < 0 same dimension
_C.MODEL.FBNET.DET_HEAD_LAST_SCALE = 1.0
_C.MODEL.FBNET.DET_HEAD_BLOCKS = []
# overwrite the stride for the head, 0 to use original value
_C.MODEL.FBNET.DET_HEAD_STRIDE = 0

# > 0 scale, == 0 skip, < 0 same dimension
_C.MODEL.FBNET.KPTS_HEAD_LAST_SCALE = 0.0
_C.MODEL.FBNET.KPTS_HEAD_BLOCKS = []
# overwrite the stride for the head, 0 to use original value
_C.MODEL.FBNET.KPTS_HEAD_STRIDE = 0

# > 0 scale, == 0 skip, < 0 same dimension
_C.MODEL.FBNET.MASK_HEAD_LAST_SCALE = 0.0
_C.MODEL.FBNET.MASK_HEAD_BLOCKS = []
# overwrite the stride for the head, 0 to use original value
_C.MODEL.FBNET.MASK_HEAD_STRIDE = 0

# 0 to use all blocks defined in arch_def
_C.MODEL.FBNET.RPN_HEAD_BLOCKS = 0
_C.MODEL.FBNET.RPN_BN_TYPE = ""

_C.MODEL.DISPNET_ON = True
_C.MODEL.DISPNET = CN()
_C.MODEL.DISPNET.POOLER_SCALES = (0.25, 0.125, 0.0625, 0.03125)
_C.MODEL.DISPNET.MAX_DISP = 48
_C.MODEL.DISPNET.MIN_DISP = -48
_C.MODEL.DISPNET.RESOLUTIONS = (28,)  # roi pooling resolution
_C.MODEL.DISPNET.DISP_RESOLUTIONS = (112,)  # disparity resolution or original roi resolution
_C.MODEL.DISPNET.SAMPLING_RATIO = 0
_C.MODEL.DISPNET.SINGLE_MODAL_WEIGHTED_AVERAGE = False
_C.MODEL.DISPNET.CONV_LAYERS = ()
_C.MODEL.DISPNET.LOSS_WEIGHT = 1.0
_C.MODEL.DISPNET.DILATE_RADIUS = 0
_C.MODEL.DISPNET.LEVELMAPMETHOD = 'nearest'
_C.MODEL.DISPNET.IS_MODULE = True
_C.MODEL.DISPNET.TRAINED_MODEL = ''
_C.MODEL.DISPNET.MAX_ROI_FOR_TRAINING = 8
_C.MODEL.DISPNET.ROI_MIN_SCORE = 0.05
_C.MODEL.DISPNET.MAX_REL_DEPTH = 12
_C.MODEL.DISPNET.MIN_REL_DEPTH = -12
_C.MODEL.DISPNET.INTERVAL = 2
# _C.MODEL.DISPNET.DECONV = False

# ---------------------------------------------------------------------------- #
# Solver
# ---------------------------------------------------------------------------- #
_C.SOLVER = CN()
_C.SOLVER.MAX_ITER = 40000

_C.SOLVER.BASE_LR = 0.001
_C.SOLVER.BIAS_LR_FACTOR = 2

_C.SOLVER.MOMENTUM = 0.9

_C.SOLVER.WEIGHT_DECAY = 0.0005
_C.SOLVER.WEIGHT_DECAY_BIAS = 0

_C.SOLVER.GAMMA = 0.1
_C.SOLVER.STEPS = (30000,)

_C.SOLVER.WARMUP_FACTOR = 1.0 / 3
_C.SOLVER.WARMUP_ITERS = 500
_C.SOLVER.WARMUP_METHOD = "linear"
_C.SOLVER.OPTIMIZER = 'SGD'
_C.SOLVER.SCHEDULER = 'WarmupMultiStepLR'
_C.SOLVER.UNCERT_LOSS_WEIGHT = 0  # 0 represents not using uncert, otherwise this num must equal to the number of loss items

_C.SOLVER.CHECKPOINT_PERIOD = 2500
_C.SOLVER.LOAD_OPTIMIZER = True
_C.SOLVER.LOAD_SCHEDULER = True
_C.SOLVER.TRAIN_2D = True
_C.SOLVER.TRAIN_PSM = False
_C.SOLVER.TRAIN_PC = False
# _C.SOLVER.TRAIN_RCNN = False
_C.SOLVER.FIX_BACKBONE = False
_C.SOLVER.FIX_RPN = False
_C.SOLVER.FIX_BOX_HEAD = False
_C.SOLVER.FIX_MASK_HEAD = False
_C.SOLVER.FIX_SHAPE_HEAD = False
_C.SOLVER.FIX_DISPARITY = False
_C.SOLVER.FIX_POINTRCNN_RPN = False
_C.SOLVER.FIX_POINTCLOUD = False
_C.SOLVER.PRINT_INTERVAL = 20
_C.SOLVER.PRINT_ITERATION = False
_C.SOLVER.DO_GRAD_CLIP = False
_C.SOLVER.GRAD_CLIP = 1.0
_C.SOLVER.ALLOW_EXCEPTION = False
_C.SOLVER.OFFLINE_2D_PREDICTIONS = ''
_C.SOLVER.REMOVE_EMPTY_ANNOTATIONS_TRAIN = True

# Number of images per batch
# This is global, so if we have 8 GPUs and IMS_PER_BATCH = 16, each GPU will
# see 2 images per batch
_C.SOLVER.IMS_PER_BATCH = 16

# ---------------------------------------------------------------------------- #
# Specific test options
# ---------------------------------------------------------------------------- #
_C.TEST = CN()
_C.TEST.EXPECTED_RESULTS = []
_C.TEST.EXPECTED_RESULTS_SIGMA_TOL = 4
# Number of images per batch
# This is global, so if we have 8 GPUs and IMS_PER_BATCH = 16, each GPU will
# see 2 images per batch
_C.TEST.IMS_PER_BATCH = 8
# Number of detections per image
_C.TEST.DETECTIONS_PER_IMG = 100
# recompute predictions at test time, load cache when False
_C.TEST.FORCE_RECOMPUTE = True

# ---------------------------------------------------------------------------- #
# Misc options
# ---------------------------------------------------------------------------- #
_C.OUTPUT_DIR = "."

_C.PATHS_CATALOG = os.path.join(os.path.dirname(__file__), "paths_catalog.py")
